home *** CD-ROM | disk | FTP | other *** search
- /** kviksl.c
- ** kvik standard library routines.
- **
- ** Written by and Copyright 1994 Asher Hoskins.
- **
- ** The author retains copyright on this implementation. Permission for
- ** educational and non-profit use is granted to all. If you're planning to
- ** make money with this or any code derived from it, check with the author
- ** first.
- **/
-
- #include <stdio.h>
- #include "systypes.h"
- #include "systimeb.h"
- #include "timea.h"
- #include <ctype.h>
- #include <math.h>
- #include "kvikmath.h"
- #include "kvik_obj_types.h"
- #include "kvikrt.h"
- #include "kviksl.h"
-
- #define PI 3.141592654
- #define MINUSZERO (0x8000) /* any kviknum >= this is negative */
- #define LINEFEED (5000) /* kviknum for 0,25 */
-
- static kviknum hournum(void);
- static void writenum(kviknum, double, int);
- static double readnum(int *);
- static void add_character_to_packed(kviknum *, kviknum *, int);
- static void print_character_from_packed(kviknum *, kviknum, int);
- extern data_area_t *data;
-
- int stdlib(int num, int r[], int p[], dp_t d[], int *gd)
- {
- int ti, ti2;
- double td;
- kviknum tk;
- FILE *outf;
- data_area_t *data_p;
-
- switch (num) {
-
- case 11:
- r[0] = doub2kvik(kvik2doub(r[0]) * kvik2doub(r[1]) * 20000.0);
- break;
-
- case 12:
- r[0] = doub2kvik(floor(kvik2doub(r[0]) / kvik2doub(r[1])) / 20000.0);
- break;
-
- case 21:
- r[0] = doub2kvik(kvik2doub(r[0]) / 400.0);
- break;
-
- case 22:
- r[0] = doub2kvik(kvik2doub(r[0])*400.0 - floor(kvik2doub(r[0])*400.0));
- break;
-
- case 31:
- r[0] = doub2kvik(kvik2doub(r[0]) * kvik2doub(r[1]) * 400.0);
- break;
-
- case 32:
- r[0] = doub2kvik((kvik2doub(r[0]) / kvik2doub(r[1])) / 400.0);
- break;
-
- case 48:
- r[0] = input_baudot();
- break;
- case 49:
- break;
-
- case 100:
- writenum(r[0], kvik2doub(r[0]), 5);
- break;
- case 101:
- break;
-
- case 150:
- r[0] = doub2kvik(readnum(&ti));
- if (ti == EOF)
- r[0] = OVERFLOW;
- break;
- case 151:
- break;
-
- case 200:
- printf("\r\n");
- break;
- case 201:
- break;
-
- case 250:
- /* This should really wait for CRLF, not just LF. */
- while (getchar() != '\n')
- ;
- break;
- case 251:
- break;
-
- case 300:
- writenum(r[0], kvik2doub(r[0])*20000.0, 0);
- break;
- case 301:
- break;
-
- case 302:
- writenum(r[0], kvik2doub(r[0])*400.0, 2);
- break;
- case 303:
- break;
-
- case 350:
- r[0] = doub2kvik(readnum(&ti)/20000.0);
- if (ti == EOF)
- r[0] = OVERFLOW;
- break;
- case 351:
- break;
-
- case 352:
- r[0] = doub2kvik(readnum(&ti)/400.0);
- if (ti == EOF)
- r[0] = OVERFLOW;
- break;
- case 353:
- break;
-
- case 400:
- td = kvik2doub(r[0]);
- if (td >= 0.0)
- r[0] = doub2kvik(sqrt(td));
- else
- r[0] = OVERFLOW;
- break;
-
- case 450:
- if (r[0] != OVERFLOW) {
- td = kvik2doub(r[0]) * PI;
- r[0] = doub2kvik(sin(td));
- }
- break;
-
- case 460:
- if (r[0] != OVERFLOW) {
- td = kvik2doub(r[0]) * PI;
- r[0] = doub2kvik(cos(td));
- }
- break;
-
- case 470:
- if (r[0] != OVERFLOW) {
- td = kvik2doub(r[0]) * 400.0;
- r[0] = doub2kvik(atan(td) / (PI/2));
- }
- break;
-
- case 480:
- if (r[0] != OVERFLOW) {
- td = kvik2doub(r[0]) + 1.0;
- r[0] = doub2kvik(log2(td) / 400.0);
- }
- break;
-
- case 490:
- if (r[0] != OVERFLOW) {
- td = kvik2doub(r[0]);
- r[0] = doub2kvik(pow(2, td) - 1);
- }
- break;
-
- case 530:
- if (d[0].start != NULL) {
- ti = d[0].offset;
- tk = 0;
- while (ti < d[0].size && tk != LINEFEED) {
- tk = input_baudot();
- if (tk >= MINUSZERO)
- tk = LINEFEED;
- d[0].start[ti] = tk;
- ti++;
- }
- if (ti == d[0].size)
- d[0].start[ti-1] = LINEFEED;
- }
- else {
- puts("KVIK: TRIED TO READ LINE INTO UNINITIALISED STORAGE");
- exit(1);
- }
- break;
- case 531:
- break;
-
- case 540:
- if (d[0].start != NULL) {
- ti = d[0].offset;
- while (ti < d[0].size && d[0].start[ti] != LINEFEED) {
- output_baudot(d[0].start[ti]);
- ti++;
- }
- putchar('\n');
- }
- else {
- puts("KVIK: TRIED TO WRITE LINE FROM UNINITIALISED STORAGE");
- exit(1);
- }
- break;
- case 541:
- break;
-
- case 550:
- if (d[0].start != NULL) {
- ti = d[0].offset;
- tk = 0;
- while (ti < d[0].size && tk != LINEFEED) {
- d[0].start[ti] = 0;
- add_character_to_packed(&tk, &d[0].start[ti], 0);
- add_character_to_packed(&tk, &d[0].start[ti], 5);
- add_character_to_packed(&tk, &d[0].start[ti], 10);
- ti++;
- }
- if (ti == d[0].size)
- d[0].start[ti-1] = LINEFEED;
- }
- else {
- puts("KVIK: TRIED TO READ LINE INTO UNINITIALISED STORAGE");
- exit(1);
- }
- break;
- case 551:
- break;
-
- case 560:
- if (d[0].start != NULL) {
- ti = d[0].offset;
- tk = 0;
- while (ti < d[0].size && tk != LINEFEED) {
- print_character_from_packed(&tk, d[0].start[ti], 0);
- print_character_from_packed(&tk, d[0].start[ti], 5);
- print_character_from_packed(&tk, d[0].start[ti], 10);
- ti++;
- }
- putchar('\n');
- }
- else {
- puts("KVIK: TRIED TO WRITE LINE FROM UNINITIALISED STORAGE");
- exit(1);
- }
- break;
- case 561:
- break;
-
- case 666:
- puts("KVIK: EMERGENCY STOP");
- exit(1);
-
- case 888:
- puts("KVIK: DUMPING STATE");
- if ((outf = fopen("k.state.c", "w")) == NULL) {
- puts("KVIK: CANNOT OPEN STATE FILE");
- exit(1);
- }
- data_p = data;
- while (data_p != NULL) {
- fprintf(outf, "store = (kviknum *) alloc_storage(%d, %d, 0);\n",
- data_p->id, data_p->size);
- for (ti2 = 0; ti2 < data_p->size; ti2++)
- fprintf(outf, "store[%d] = %d;\n", ti2, data_p->start[ti2]);
- data_p = data_p->next;
- }
- for (ti = 0; ti < 10; ti++) {
- fprintf(outf, "r[%d] = %d;\n", ti, r[ti]);
- fprintf(outf, "p[%d] = %d;\n", ti, p[ti]);
- if (d[ti].start != NULL)
- fprintf(outf, "set_dp_intoff(&d[%d], %d, %d);\n", ti, d[ti].id,
- d[ti].offset);
- }
- fclose(outf);
- puts("KVIK: DUMPED STATE");
- break;
-
- case 900:
- r[0] = hournum();
- break;
-
- default:
- return(0);
- }
-
- *gd = p[0];
- return(1);
- }
-
- /** Return the hour number / 24.0 in kviknum format.
- **/
-
- static kviknum hournum(void)
- {
- time_t t;
- struct tm *lt;
-
- t = time(NULL);
- lt = localtime(&t);
-
- return(doub2kvik(lt->tm_hour / 24.0));
- }
-
- /** Write a number to the screen, using ',' instead of a decimal point.
- **/
-
- static void writenum(kviknum k, double d, int prec)
- {
- static char s[30];
- int i;
-
- if (k == OVERFLOW) {
- printf("OVERFLOW ");
- return;
- }
-
- sprintf(s, "%.*f ", prec, d);
- if (prec > 0) {
- for (i = 0; s[i] != '.'; i++)
- ;
- s[i] = ',';
- }
- printf(s);
- }
-
- /** Read a number from the keyboard, using ',' instead of a decimal point.
- **/
-
- static double readnum(int *c)
- {
- static char s[30];
- int i;
- double d;
-
- for (i=0; i<30 && isspace(s[i] = getchar()); i++)
- ;
- if (s[i] == ',')
- s[i] = '.';
- i++;
- for (; i<30 && (isdigit(s[i] = *c = getchar()) || s[i] == ','); i++)
- if (s[i] == ',')
- s[i] = '.';
-
- if (i == 30 || *c == EOF)
- return(0.0); /* something probably went wrong */
-
- s[i] = '\0';
- sscanf(s, "%lf", &d);
-
- return(d);
- }
-
- /** Read a baudot character from the keyboard and add it to 'num', shifted
- ** left by 'shift' places. The character read is returned in c. If the
- ** function is entered with c set to LINEFEED it is assumed that the end
- ** of the line has just been read and so the function exits without doing
- ** anything.
- **
- ** NOTE: if the kviknum format changes then the 625 (= 20000/32) will
- ** have to be changed.
- **/
-
- static void add_character_to_packed(kviknum *c, kviknum *num, int shift)
- {
- if (*c == LINEFEED)
- return;
- *c = input_baudot();
- if (*c >= MINUSZERO)
- *c = LINEFEED;
- *num |= (*c / 625) << shift;
- }
-
- /** Write the baudot character stored in bits (shift):(shift+4) of num,
- ** unless c is LINEFEED. Set c to the kviknum of the character printed.
- **
- ** NOTE: if the kviknum format changes then the 625 (= 20000/32) will
- ** have to be changed.
- **/
-
- static void print_character_from_packed(kviknum *c, kviknum num, int shift)
- {
- if (*c == LINEFEED)
- return;
- *c = ((num >> shift) & 0x1f) * 625;
- output_baudot(*c);
- }
-
-